package com.example.yin.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.ServiceException;
import com.aliyun.oss.model.PutObjectResult;
import com.example.yin.config.AliyunOssConfig;
import com.example.yin.service.FileService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author Johnson
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class FileServiceImpl implements FileService {

    private final OSS ossClient;

    private final AliyunOssConfig aliyunOssConfig;

    private final ThreadPoolExecutor executor;

    /**
     * @param multipartFile 需要上传的图片，可变参数
     * @description 上传图片
     * @method upload
     * @author Johnson
     * @date 2022/9/13 13:21
     **/
    public List<String> multiUpload(List<MultipartFile> multipartFile) {
        log.info("开始上传照片……");
        // 图片上传至阿里云OSS，设置返回路径集合
        List<String> responseUrls = new ArrayList<>();
        // 用户上传文件时指定的前缀，即存放在以时间命名的文件夹内
        String dir = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        CompletableFuture<PutObjectResult> future = null;
        for (MultipartFile file : multipartFile) {
            String originalFilename = file.getOriginalFilename();
            // 设置上传到云存储的文件名，规则为"当前时间-UUID.源文件后缀名"
            String cloudFileName = new SimpleDateFormat("HH:mm:ss").format(new Date()) +
                    "-" +
                    UUID.randomUUID() +
                    //.append("-")
                    //.append(originalFilename)
                    getExtensionName(originalFilename);
            // 设置上传到云存储的路径
            String cloudPath = dir + "/" + cloudFileName;
            // 线程池异步上传图片
            future = CompletableFuture.supplyAsync(() -> {
                try {
                    // 图片上传
                    return ossClient.putObject(aliyunOssConfig.getBucket(), cloudPath, file.getInputStream());
                } catch (IOException e) {
                    throw new ServiceException("上传失败");
                }
            }, executor).whenComplete((res, exception) -> {
                // 判断是否出现异常
                if (!ObjectUtils.isEmpty(exception)) {
                    throw new ServiceException("网络错误");
                }
                // 判断是否正确返回，将图片链接添加到集合中
                if (!ObjectUtils.isEmpty(res)) {
                    responseUrls.add(aliyunOssConfig.getMarketHost() + "/" + cloudPath);
                }
            });
        }
        // 等待线程执行完毕
        if (future != null) {
            future.join();
        }
        // 返回上传的图片链接集合
        log.info("返回的路径为{}", responseUrls);
        return responseUrls;
    }

    /**
     * @param filename 文件名
     * @description 获取文件拓展名
     * @method getExtensionName
     * @author Johnson
     * @date 2022/9/21 21:21
     **/
    private String getExtensionName(String filename) {
        if ((filename != null) && (!filename.isEmpty())) {
            int dot = filename.lastIndexOf('.');
            if ((dot > -1) && (dot < (filename.length() - 1))) {
                return filename.substring(dot);
            }
        }
        return filename;
    }

    /**
     * 普通文件上传
     */
    public String upload(MultipartFile file) {
        log.info("\n<<------OSS文件上传开始-------->>\n" + file.getOriginalFilename());
        String dir = new SimpleDateFormat("yyyyMMdd").format(new Date());
        // 判断文件
        String originalFilename = file.getOriginalFilename();
        String cloudFileName = new SimpleDateFormat("HHmmss").format(new Date()) +
                "-" +
                UUID.randomUUID() +
                getExtensionName(originalFilename);
        // 设置上传到云存储的路径
        String cloudPath = dir + "/" + cloudFileName;
        try {
            // 图片上传
            PutObjectResult result = ossClient.putObject(aliyunOssConfig.getBucket(), cloudPath, file.getInputStream());
            if (result != null) {
                log.info("\n<<------OSS文件上传成功------>>\n " + aliyunOssConfig.getMarketHost() + "/" + cloudPath);
                return aliyunOssConfig.getMarketHost() + "/" + cloudPath;
            }
        } catch (IOException e) {
            throw new ServiceException("上传失败");
        }
        return null;
    }

}
